from torch_geometric_temporal.dataset import ChickenpoxDatasetLoader
from torch_geometric_temporal.signal import temporal_signal_split
= ChickenpoxDatasetLoader()
loader
= loader.get_dataset()
dataset
= temporal_signal_split(dataset, train_ratio=0.2) train_dataset, test_dataset
Questions of PyTorch Geometric Temporal
PyTorch Geometric Temporal
PyTorch Geometric Temporal
PyTorch Geometric Temporal: Spatiotemporal Signal Processing with Neural Machine Learning Models
Applications
Epidemiological Forecasting
import torch
import torch.nn.functional as F
from torch_geometric_temporal.nn.recurrent import DCRNN
class RecurrentGCN(torch.nn.Module):
def __init__(self, node_features):
super(RecurrentGCN, self).__init__()
self.recurrent = DCRNN(node_features, 32, 1)
self.linear = torch.nn.Linear(32, 1)
def forward(self, x, edge_index, edge_weight):
= self.recurrent(x, edge_index, edge_weight)
h = F.relu(h)
h = self.linear(h)
h return h
from tqdm import tqdm
= RecurrentGCN(node_features = 4)
model
= torch.optim.Adam(model.parameters(), lr=0.01)
optimizer
model.train()
for epoch in tqdm(range(200)):
= 0
cost for time, snapshot in enumerate(train_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost
cost.backward()
optimizer.step()
optimizer.zero_grad()
###########################################################
# I added this to check the shape.
print(y_hat.shape,snapshot.y.shape,(y_hat-snapshot.y).shape)
100%|██████████| 200/200 [02:40<00:00, 1.24it/s]
torch.Size([20, 1]) torch.Size([20]) torch.Size([20, 20])
eval()
model.= 0
cost for time, snapshot in enumerate(test_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost = cost.item()
cost print("MSE: {:.4f}".format(cost))
# >>> MSE: 1.0232
MSE: 1.0247
Shape Check (1)
= torch.randn(20, 1) a
= torch.randn(20) b
= a-b c
print(a.size(),b.size(),c.size())
torch.Size([20, 1]) torch.Size([20]) torch.Size([20, 20])
Doesn’t it have to ‘y_hat’ be the same shape as snapshot.y?
- If we want to compare the y_hat from the model with the values y, the same shape is appropriate to evaluate.
from tqdm import tqdm
= RecurrentGCN(node_features = 4)
model
= torch.optim.Adam(model.parameters(), lr=0.01)
optimizer
model.train()
for epoch in tqdm(range(200)):
= 0
cost for time, snapshot in enumerate(train_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr).reshape(-1)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost
cost.backward()
optimizer.step()
optimizer.zero_grad()
###########################################################
# I added this to check the shape.
print(y_hat.shape,snapshot.y.shape,(y_hat-snapshot.y).shape)
100%|██████████| 200/200 [01:27<00:00, 2.30it/s]
torch.Size([20]) torch.Size([20]) torch.Size([20])
eval()
model.= 0
cost for time, snapshot in enumerate(test_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost = cost.item()
cost print("MSE: {:.4f}".format(cost))
# >>> MSE: 1.0232
MSE: 1.2844
Shape Check (2)
= torch.randn(20, 1).reshape(-1) a
= torch.randn(20) b
= a-b c
print(a.size(),b.size(),c.size())
torch.Size([20]) torch.Size([20]) torch.Size([20])
Web Traffic Prediction
from torch_geometric_temporal.dataset import WikiMathsDatasetLoader
from torch_geometric_temporal.signal import temporal_signal_split
= WikiMathsDatasetLoader()
loader
= loader.get_dataset(lags=14)
dataset
= temporal_signal_split(dataset, train_ratio=0.5) train_dataset, test_dataset
import torch
import torch.nn.functional as F
from torch_geometric_temporal.nn.recurrent import GConvGRU
class RecurrentGCN(torch.nn.Module):
def __init__(self, node_features, filters):
super(RecurrentGCN, self).__init__()
self.recurrent = GConvGRU(node_features, filters, 2)
self.linear = torch.nn.Linear(filters, 1)
def forward(self, x, edge_index, edge_weight):
= self.recurrent(x, edge_index, edge_weight)
h = F.relu(h)
h = self.linear(h)
h return h
from tqdm import tqdm
= RecurrentGCN(node_features=14, filters=32)
model
= torch.optim.Adam(model.parameters(), lr=0.01)
optimizer
model.train()
for epoch in tqdm(range(50)):
for time, snapshot in enumerate(train_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = torch.mean((y_hat-snapshot.y)**2)
cost
cost.backward()
optimizer.step()
optimizer.zero_grad()
###########################################################
# I added this to check the shape.
print(y_hat.shape,snapshot.y.shape,(y_hat-snapshot.y).shape)
100%|██████████| 50/50 [31:26<00:00, 37.73s/it]
torch.Size([1068, 1]) torch.Size([1068]) torch.Size([1068, 1068])
eval()
model.= 0
cost for time, snapshot in enumerate(test_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost = cost.item()
cost print("MSE: {:.4f}".format(cost))
# >>> MSE: 0.7760
MSE: 0.7939
Shape Check (1)
= torch.randn(1068, 1) a
= torch.randn(1068) b
= a-b c
print(a.size(),b.size(),c.size())
torch.Size([1068, 1]) torch.Size([1068]) torch.Size([1068, 1068])
If the code changes the shape of y_hat?
from tqdm import tqdm
= RecurrentGCN(node_features=14, filters=32)
model
= torch.optim.Adam(model.parameters(), lr=0.01)
optimizer
model.train()
for epoch in tqdm(range(50)):
for time, snapshot in enumerate(train_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = torch.mean((y_hat-snapshot.y)**2)
cost
cost.backward()
optimizer.step()
optimizer.zero_grad()
###########################################################
# I added this to check the shape.
print(y_hat.shape,snapshot.y.shape,(y_hat-snapshot.y).shape)
100%|██████████| 50/50 [36:39<00:00, 43.99s/it]
torch.Size([1068, 1]) torch.Size([1068]) torch.Size([1068, 1068])
eval()
model.= 0
cost for time, snapshot in enumerate(test_dataset):
= model(snapshot.x, snapshot.edge_index, snapshot.edge_attr)
y_hat = cost + torch.mean((y_hat-snapshot.y)**2)
cost = cost / (time+1)
cost = cost.item()
cost print("MSE: {:.4f}".format(cost))
# >>> MSE: 0.7760
MSE: 0.7807
Shape Check (2)
= torch.randn(1068, 1).reshape(-1) a
= torch.randn(1068) b
= a-b c
print(a.size(),b.size(),c.size())
torch.Size([1068]) torch.Size([1068]) torch.Size([1068])
Fix : https://github.com/benedekrozemberczki/pytorch_geometric_temporal/issues/231